﻿/*-------------------------------------------------------------------------
 * CLR版本:     4.0.30319.42000
 * 创建人:      song
 * 创建时间：   2024/4/9 18:18:22
 * 功 能：      条件字段自动化绘制 目前支持 Enum 和 bool
 *-------------------------------------------------------------------------*/

using System;
using UnityEditor;
#if UNITY_EDITOR
using UnityEditor;
#endif
using UnityEngine;

namespace Function.SerializedPropertyAttribute
{
    [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
    public class ConditionalFieldAttribute : PropertyAttribute
    {
        private readonly string _fieldToCheck;
        private readonly bool _inverse;
        private readonly object[] _compareValues;

        public ConditionalFieldAttribute(string fieldToCheck, bool inverse = false, params object[] compareValues)
        {
            this._fieldToCheck = fieldToCheck;
            this._inverse = inverse;
            this._compareValues = compareValues;
        }

        public ConditionalFieldAttribute(string fieldToCheck, bool inverse = false)
        {
            this._fieldToCheck = fieldToCheck;
            this._inverse = inverse;
        }

#if UNITY_EDITOR
        public bool CheckPropertyVisible(SerializedProperty property)
        {
            var checkField = property.serializedObject.FindProperty(_fieldToCheck);
            if (checkField == null)
            {
                return true;
            }

            if (_compareValues != null && _compareValues.Length > 0)
            {
                if (checkField.propertyType == SerializedPropertyType.Enum)
                {
                    bool check = _inverse;
                    foreach (var compareValue in _compareValues)
                    {
                        if (checkField.enumValueIndex == (int)compareValue)
                        {
                            return check;
                        }
                    }

                    return !check;
                }
                else if (checkField.propertyType == SerializedPropertyType.String)
                {
                    bool check = _inverse;
                    foreach (var compareValue in _compareValues)
                    {
                        if (checkField.stringValue == (string)compareValue)
                        {
                            return check;
                        }
                    }

                    return !check;
                }
            }
            else
            {
                if (checkField.propertyType == SerializedPropertyType.Boolean)
                {
                    return checkField.boolValue == _inverse;
                }
            }

            return true;
        }
#endif
    }
}

#if UNITY_EDITOR
namespace Function.SerializedPropertyAttribute
{
    using UnityEditor;

    [CustomPropertyDrawer(typeof(ConditionalFieldAttribute))]
    public class ConditionalFieldAttributeDrawer : PropertyDrawer
    {
        private ConditionalFieldAttribute Attribute =>
            _attribute ??= attribute as ConditionalFieldAttribute;

        private ConditionalFieldAttribute _attribute;

        private bool _toShow = true;

        public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
        {
            _toShow = Attribute.CheckPropertyVisible(property);
            return _toShow ? EditorGUI.GetPropertyHeight(property) : 0;
        }

        public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
        {
            if (_toShow) EditorGUI.PropertyField(position, property, label, true);
        }
    }
}
#endif